﻿using System;
using HK.Core.Common.Data;
using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.Serializable.Attribute;
using HK.Core.Serializable.Protocol.Data;
using HK.Core.Utils;
using UnityEngine;

namespace HK.Core.Serializable.Data
{
    /// <summary>
    /// 序列化资产头部
    /// </summary>
    [Serializable]
    public class SAssetHeader : JsonData<SAssetHeader>, ISAssetHeader
    {

#region Create

        /// <summary>
        /// 创建可序列化资产头部信息
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iEditor">编辑器标志位</param>
        /// <param name="iCreateTime">创建时间</param>
        /// <returns>可序列化资产头部信息</returns>
        public static SAssetHeader Create(bool iStatic, bool iEditor = false, long iCreateTime = 0L)
        {
            var createTime = iCreateTime;
            if (0 >= createTime)
            {
                createTime = UtilsTime.GetCurDateTimeTicks();
            }

            return new SAssetHeader(iStatic, iEditor) { createTime = createTime };
        }

#endregion

        /// <summary>
        /// 保护构造函数
        /// </summary>
        protected SAssetHeader()
        {
            createTime = UtilsTime.GetCurDateTimeTicks();
            updateTime = UtilsTime.GetCurDateTimeTicks();
        }
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iEditor">编辑器标志位</param>
        protected SAssetHeader(bool iStatic, bool iEditor = false) : this()
        {
            Static = iStatic;
            Editor = iEditor;
        }

#region Mode
        
        [SerializeField, HideInInspector]
        private int mode = (int)SAssetMode.Static;
        /// <summary>
        /// 序列化文件模式
        /// </summary>
        public int Mode => mode;

        /// <summary>
        /// 编辑器标志位
        /// </summary>
        public bool Editor
        {
            get => UtilsBytes.CheckBytes(mode, (int)SAssetMode.Editor); 
            private set => mode = UtilsBytes.SetBytes(mode, (int)SAssetMode.Editor, value);
        }

        /// <summary>
        /// 静态文件标志位
        /// </summary>
        public bool Static 
        {
            get => UtilsBytes.CheckBytes(mode, (int)SAssetMode.Static); 
            internal set => mode = UtilsBytes.SetBytes(mode, (int)SAssetMode.Static, value);
        }

#endregion
        
        [SerializeField, SVersion("版本号")]
        private SAssetVersion version = SAssetVersion.Create();
        /// <summary>
        /// 版本信息
        /// </summary>
        public ISAssetVersion Version => version;

        [SerializeField, DateTime("创建日期")]
        private long createTime = 0L;
        /// <summary>
        /// 创建时间Ticks
        /// </summary>
        public long CreateTimeTicks => createTime;
        /// <summary>
        /// 创建时间
        /// <para>* 格式 : YYYY/MM/DD HH:MM:SS</para>
        /// </summary>
        public string CreateTimeTxt => UtilsTime.ConvertByFormat(createTime);
        
        [SerializeField, DateTime("更新日期")]
        private long updateTime = 0L;
        /// <summary>
        /// 更新时间Ticks
        /// </summary>
        public long UpdateTimeTicks => updateTime;
        /// <summary>
        /// 更新时间
        /// <para>* 格式 : YYYY/MM/DD HH:MM:SS</para>
        /// </summary>
        public string UpdateTimeTxt => UtilsTime.ConvertByFormat(updateTime);
        
        /// <summary>
        /// 目录
        /// </summary>
        public string Dir => UtilsSAssets.GetAssetPath(Editor);

        /// <summary>
        /// 刷新
        /// </summary>
        public void Refresh()
        {
            updateTime = UtilsTime.GetCurDateTimeTicks();
        }

        /// <summary>
        /// 应用数据
        /// </summary>
        /// <param name="iData">数据</param>
        /// <param name="iImport">导入标志位(true:从相应的*.json文件导入; false:反之;)</param>
        /// <returns>true:有变更; false:无变更;</returns>
        public override bool ApplyData(IJsonData iData, bool iImport = false)
        {
            if (null == iData || !iData.Valid) return false;

            var dirty = base.ApplyData(iData, iImport);
            if (dirty && !iImport)
            {
                Dirty = true;
            }

            if (iData is ISAssetHeader header)
            {
                mode = UpdateValue(mode, header.Mode, iImport);
                
                dirty = version.ApplyData(header.Version);
                if (dirty && !iImport)
                {
                    Dirty = true;
                }

                createTime = UpdateValue(createTime, header.CreateTimeTicks, iImport);
                updateTime = UpdateValue(updateTime, header.UpdateTimeTicks, iImport);
            }

            // 刷新
            if (Dirty)
            {
                Refresh();
            }
            
            return Dirty;
        }

        /// <summary>
        /// 清空
        /// </summary>
        public override void Clear()
        {
            base.Clear();
            
            mode = (int)SAssetMode.Static;
            version.Clear();
            createTime = 0L;
            updateTime = 0L;
        }
    }
}
